#ifndef __GAME_EVENT_H__
#define __GAME_EVENT_H__

#include "game_def.h"
#include "game_thread.h"
#include "game_tl.h"
#include "game_ev.h"
#include <vector>
#include <map>
#include <deque>
#include <string.h>

#ifndef C_MAX_EVENT_THREAD
#define C_MAX_EVENT_THREAD 1
#endif

class CGameEventListener;
class CGameEventDispatcher;


class CGameEvent:public CGameRef{
public:
  typedef std::string Type;
  CGameEvent(const char* type,CGameRef* currentTarget);
  /** Destructor */
  virtual ~CGameEvent(){
    // C_LOG("%s","Event Dealloc.");
  };
  /** @brief Gets current target of the event
    * @return The target with which the event associates.
    * @note It onlys be available when the event listener is associated with node. 
    *       It returns 0 when the listener is associated with fixed priority.
    */
  inline CGameRef* getCurrentTarget() { return _currentTarget; };
  const Type& getType() const {
    return _type;
  };

  /**
   * @brief 防止对事件流中当前节点的后续节点中的所有事件侦听器进行处理。
   * 
   */
  void stopPropagation(){
    _stopPropagation = TRUE;
  }

  void release();

  
  static const char* CONNECT;
  static const char* INIT;
  static const char* CLOSE;
protected:
  Type _type;     ///< Event type
  CGameRef* _currentTarget;  ///< Current target
  BOOL _stopPropagation = FALSE;
protected:
  friend class CGameEventListener;
  friend class CGameEventDispatcher;
};


typedef CMemFun_t<CGameObject,BOOL,CGameEvent*> CGameEventHandler;

namespace CGame{
namespace Event{

  
  typedef std::deque<CGameEvent*> EventList_t;
  typedef std::vector<CGameEventHandler> EventHanderList;
  typedef std::map<CGameEvent::Type,EventHanderList*> ListenerMap_t;


  


  struct EventContext_t{
    event* _ev;
    CGameEventDispatcher* _this;
    CGameEvent* _event;
  };

  

  template <typename TYPE, void (TYPE::*onEvent)(EventContext_t*) >  
  void __event_cb(int sock, short which, void *arg) ;


}}

class ICGameEventDispatcher:virtual public CGameRef{
public:
  virtual void addEventListener(const CGameEvent::Type& type,CGameEventHandler handler) = 0;
  virtual void dispatch(CGameEvent* event) = 0;
  virtual void removeEventListener(const CGameEvent::Type& type,CGameEventHandler handler) = 0;
};

class CGameEventDispatcher:public ICGameEventDispatcher{
  template <typename TYPE, void (TYPE::*onEvent)(CGame::Event::EventContext_t*) >  
  friend void CGame::Event::__event_cb(int sock, short which, void *arg);
protected:
  virtual void onEvent(CGame::Event::EventContext_t* ctx);
  /** Listeners map */
  CGame::Event::ListenerMap_t _listenerMap;
  event_base* _evbase;

  virtual void doRemoveEventListener(const CGameEvent::Type& type,CGameEventHandler handler);
public:
  virtual BOOL init(event_base* evbase);
  virtual BOOL init();

  virtual void addEventListener(const CGameEvent::Type& type,CGameEventHandler handler);
  virtual void removeEventListener(const CGameEvent::Type& type,CGameEventHandler handler);
  virtual void dispatch(CGameEvent* event);
  CGameEventDispatcher();
  virtual ~CGameEventDispatcher();
};

#endif
